import { Args, Int, Mutation, Query, Resolver } from '@nestjs/graphql';
import { CREATE_POWER, DELETE_POWER, GqlAuthGuard, GqlCurrentUser, MakeGqlAuthPowerGuard, UPDATE_POWER, VIEW_POWER } from 'src/auth/auth.guard';
import { QuestionService } from './question.service';
import { PrismaService } from '@app/prisma';
import { SysTestPaperEntity } from '@app/prisma/sys.test.paper.entity/sys.test.paper.entity';
import { UseGuards } from '@nestjs/common';
import { SysUserEntity } from '@app/prisma/sys.user.entity/sys.user.entity';
import { SysTestQuestionEntity } from '@app/prisma/sys.test.question.entity/sys.test.question.entity';
import { SysPaperEntity } from '@app/prisma/sys.paper.entity/sys.paper.entity';
import { Prisma, question_type } from '@prisma/client';
import { SysWrongEntity } from '@app/prisma/sys.wrong.entity/sys.wrong.entity';
import { TestGuard } from 'src/test/test.resolver';


// export const QuestionGuard = MakeGqlAuthPowerGuard("/question", "题目管理")
@Resolver()
export class QuestionResolver {
  constructor(
    private readonly service: QuestionService,
    private readonly prisma: PrismaService
  ) { }

  @Query(() => [SysTestQuestionEntity])
  @UseGuards(TestGuard([VIEW_POWER]))
  async getQuestions(
    @Args("id", { type: () => Int }) id: number,
  ) {
    return await this.prisma.sys_test_question.findMany({
      where: {
        sys_test_paperId: id
      }
    })
  }

  @Query(() => SysTestQuestionEntity)
  @UseGuards(TestGuard([VIEW_POWER]))
  async getQuestion(
    @Args("id", { type: () => Int }) id: number,
  ) {
    const data = await this.prisma.sys_test_question.findUnique({
      where: {
        id
      }
    })
    return data;
  }

  /**
   * 添加试题
   * 要求：将题目、答案中的图片保存并替换为图片链接。
   * 例如：__image__( 这里是图片的哈希 )__image__ 之类的。
   * @param sys_test_paperId 试卷ID
   */
  @Mutation(() => SysTestQuestionEntity)
  @UseGuards(TestGuard([CREATE_POWER]))
  async createQuestion(
    @Args("sys_test_paperId", { type: () => Int }) sys_test_paperId: number,
    @Args("name", { type: () => String }) name: string,
    @Args("order", { type: () => Int }) order: number,
    @Args("type", { type: () => String }) type: question_type,
    @Args("answer", { type: () => String, nullable: true, defaultValue: "见解析" }) answer: string,
    @Args("content", { type: () => String }) content: string,
    @Args("score", { type: () => Int }) score: number,
    @Args("count", { type: () => Int, nullable: true }) count?: number,
    @Args("right", { type: () => Int, nullable: true }) right?: number,
    @Args("help", { type: () => String, nullable: true, defaultValue: "略" }) help?: string
  ) {
    return await this.prisma.sys_test_question.create({
      data: {
        sys_test_paper: {
          connect: {
            id: sys_test_paperId
          }
        },
        name,
        order,
        type,
        answer,
        content,
        score,
        count,
        right,
        help
      }
    })
  }
  /**
   * 修改试题
   */
  @Mutation(() => SysTestQuestionEntity)
  @UseGuards(TestGuard([UPDATE_POWER]))
  async updateQuestion(
    @Args("id", { type: () => Int }) id: number,
    @Args("sys_test_paperId", { type: () => Int, nullable: true }) sys_test_paperId?: number,
    @Args("name", { type: () => String, nullable: true }) name?: string,
    @Args("order", { type: () => Int, nullable: true }) order?: number,
    @Args("type", { type: () => String, nullable: true }) type?: question_type,
    @Args("answer", { type: () => String, nullable: true }) answer?: string,
    @Args("content", { type: () => String, nullable: true }) content?: string,
    @Args("score", { type: () => Int, nullable: true }) score?: number,
    @Args("count", { type: () => Int, nullable: true }) count?: number,
    @Args("right", { type: () => Int, nullable: true }) right?: number,
    @Args("help", { type: () => String, nullable: true }) help?: string,
  ) {
    const find = await this.prisma.sys_test_question.findUnique({
      where: { id }
    })
    if (!find) throw new Error("问题不存在");
    const data: Prisma.sys_test_questionUpdateInput = {
      name,
      order,
      type,
      answer,
      content,
      score,
      count,
      right,
      help,
    };
    if (!!sys_test_paperId) {
      data.sys_test_paper = {
        connect: {
          id: sys_test_paperId
        }
      }
    }
    return await this.prisma.sys_test_question.update({
      where: { id },
      data
    })
  }
  @Mutation(() => SysTestQuestionEntity)
  @UseGuards(TestGuard([DELETE_POWER]))
  async deleteQuestion(
    @Args("id", { type: () => Int }) id: number,
  ) {
    const question = await this.prisma.sys_test_question.delete({
      where: {
        id
      }
    })
    if (!question) {
      throw new Error("试题不存在")
    }
    return question
  }

  /**
   * 随机获取试题
   * @param chapterId 章节id
   * @param data 每种题的数量
   * [{type,num}]
   */
  @Query(() => [SysTestQuestionEntity])
  @UseGuards(GqlAuthGuard)
  async randomTestQuestion(
    @Args("chapterId", { type: () => Int }) chapterId: number,
    @Args("data", { type: () => String }) data: string,
    @GqlCurrentUser() user: SysUserEntity
  ) {
    if (!await this.service.canReadChapter(chapterId, user)) throw new Error("你没有权限查看这个章节");
    const nums: [{ type, num }] = JSON.parse(data);
    const paperIds = await this.prisma.sys_test_paper.findMany({
      where: {
        sys_test_chapterId: chapterId
      },
      select: {
        id: true
      }
    }).then(res => res.map(item => item.id))
    const res = [];
    for (const { type, num } of nums) {
      const questionNum = await this.prisma.sys_test_question.count({
        where: {
          type,
          sys_test_paperId: {
            in: paperIds
          },
        }
      })
      const questions = await this.prisma.sys_test_question.findMany({
        where: {
          type,
          sys_test_paperId: {
            in: paperIds
          },
        },
        skip: Math.floor(Math.random() * (questionNum - num * 5)),
        take: num * 5
      })
      questions.sort(() => Math.random() - 0.5)
      res.concat(questions.slice(0, num))
    }
    return res;
  }



  /**
   * 难度练习
   * 这个不着急，最后再做。
   */
  @Query(() => [SysTestQuestionEntity])
  async difficultTestQuestion(
    @Args("chapterId", { type: () => Int }) chapterId: number,
    @Args("num", { type: () => Int }) num: number,
  ) {
    throw new Error("未完成");
    // const paperIds = await this.prisma.sys_test_paper.findMany({
    //   where: {
    //     sys_test_chapterId: chapterId
    //   },
    //   select: {
    //     id: true
    //   }
    // }).then(res => res.map(item => item.id))
    // const questionNum = await this.prisma.sys_test_question.count({
    //   where: {
    //     sys_test_paperId: {
    //       in: paperIds
    //     },
    //   }
    // })
    // const questions = await this.prisma.sys_test_question.findMany({
    //   where: {
    //     sys_test_paperId: {
    //       in: paperIds
    //     },
    //   },
    //   skip: Math.floor(Math.random() * (questionNum - num)),
    //   take: num,
    // })
    // return questions;
  }

  /**
   * 获取试卷并附带所有试题
   */
  @Query(() => SysTestPaperEntity)
  async queryTestPaperAndQuestions(
    @Args("id", { type: () => Int }) id: number
  ) {
    return this.prisma.sys_test_paper.findUnique({
      where: {
        id
      },
      include: {
        questions: true
      }
    })
  }

  /**
   * 提交试卷。
   * @param data 试卷数据
   * @param id 试卷ID
   * @param user 当前用户
   * 要求：
   * data是一个json字符串，结构类似于：
   * （如果不出意外的话，应该是这样的。
   * [{
   *  id:试题id
   *  answer:答案
   * }]
   * 处理该试卷的分数。
   * 已答、未答、分数、答题时间等信息。
   * 记录所有错题
   */
  @Mutation(() => Int)
  @UseGuards(GqlAuthGuard)
  async pushPaper(
    @Args("data") data: string,
    @Args("id", { type: () => Int }) id: number,
    @GqlCurrentUser() user: SysUserEntity
  ) {
    if (!await this.service.canReadPaper(id, user)) throw new Error("你没有权限查看这个试卷");
    return await this.service.pushPaper(data, id, user)
  }

  /**同上，判随机试题的卷子，不存储试卷记录
   */
  @Mutation(() => SysPaperEntity)
  @UseGuards(GqlAuthGuard)
  async judgeRandomPaper(
    @Args("chapterId", { type: () => Int }) chapterId: number,
    @Args("data") data: string,
    @GqlCurrentUser() user: SysUserEntity
  ) {
    if (!await this.service.canReadChapter(chapterId, user)) throw new Error("你没有权限查看这个章节");
    return await this.service.judgeRandomPaper(data, user)
  }

  /**
   * 获取所有错题
   */
  @Query(() => [SysWrongEntity])
  async getWrongQuestion(
    @GqlCurrentUser() user: SysUserEntity
  ) {
    return await this.prisma.sys_wrong.findMany({
      where: {
        sys_userId: user.id
      }
    })
  }


  /**
   * 获取历史试卷
   */
  @Query(() => [SysPaperEntity])
  async getHistoryPaper(
    @GqlCurrentUser() user: SysUserEntity
  ) {
    return await this.prisma.sys_paper.findMany({
      where: {
        sys_userId: user.id
      }
    })
  }

  /**
   * 删除自己的历史试卷
   */
  @Mutation(() => SysPaperEntity)
  @UseGuards(GqlAuthGuard)
  async deleteHistoryPaper(
    @Args("id", { type: () => Int }) id: number,
    @GqlCurrentUser() user: SysUserEntity
  ) {
    const paper = await this.prisma.sys_paper.findUnique({
      where: {
        id: id
      }
    });
    if (!paper) {
      throw new Error("试卷不存在");
    }
    if (paper.sys_userId != user.id) {
      throw new Error("你删别人卷子？？？");
    }
    return paper;
  }

  /**
   * 管理员获取所有历史试卷
   * 这个不着急，最后再做。
   */
  @Query(() => [SysPaperEntity])
  @UseGuards(TestGuard([VIEW_POWER]))
  async getHistoryPaperAdmin() {
    return await this.prisma.sys_paper.findMany();
  }

  /**
   * 管理员删除历史试卷
   */
  @Mutation(() => SysPaperEntity)
  @UseGuards(TestGuard([DELETE_POWER]))
  async deleteHistoryPaperAdmin() { }

  /**
   * 获取历史试卷详情
   */
  @Query(() => SysPaperEntity)
  async getHistoryPaperDetail() { }
}
